fix: handle windows hook unicode prompts - #1316
Closed
222twotwotwo wants to merge 443 commits into
Closed
Conversation
Bumps [qs](https://github.com/ljharb/qs) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `qs` from 6.15.1 to 6.15.2 - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](ljharb/qs@v6.15.1...v6.15.2) Updates `express` from 4.22.1 to 4.22.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/v4.22.2/History.md) - [Commits](expressjs/express@v4.22.1...v4.22.2) --- updated-dependencies: - dependency-name: qs dependency-version: 6.15.2 dependency-type: indirect - dependency-name: express dependency-version: 4.22.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…base#936) IntelligentMemoryManager now reads long_term_threshold and short_term_threshold from EbbinghausAlgorithm, matching EbbinghausIntelligencePlugin behavior. Add unit tests for boundary scores and custom config. Fixes oceanbase#935
…anbase#950) * fix(logging): wire LOGGING_* env vars to powermem logger file handler LoggingSettings parsed LOGGING_FILE from .env but no code attached a FileHandler to the "powermem" logger tree. SDK modules logged to stderr only; ./logs/powermem.log was never created despite being documented. Add logging_config.py with setup_powermem_logging() that reads LoggingSettings, creates a RotatingFileHandler (with optional gzip compression on rollover), and attaches it to logging.getLogger("powermem"). Call it from Memory.__init__ (SDK/CLI path) and server setup_logging() (HTTP server path). Idempotent via module-level guard. * fix(logging): propagate trace context and fix gzip log rotation Wire request_id/user_id/agent_id into powermem SDK logs via contextvars and HTTP middleware. Store compressed backups as base.N.gz to preserve backupCount semantics. Update default LOGGING_FORMAT and add unit tests.
…nd MCP (oceanbase#952) - Use module-level logger instead of root logger in 6 LLM integration modules - Add exc_info=True to ~100 logger.error() calls in agent layer except blocks - Attach TraceContextFilter to server and uvicorn loggers for request tracing - Replace plain FileHandler with CompressingRotatingFileHandler in audit logger - Make server log rotation configurable via POWERMEM_SERVER_LOG_MAX_SIZE env var - Add JSON logging mode (LOGGING_FORMAT=json) to SDK via JsonLogFormatter - Share single file handler across uvicorn loggers to prevent rotation races - Replace traceback.print_exc() with logger.exception() in CLI commands - Export all fields from LoggingSettings.to_config() and AuditSettings.to_config() - Add module logger to MCP server
… profile (oceanbase#951) When a conversation contains no extractable profile information, the LLM sometimes returns a verbose refusal instead of an empty string, bypassing the existing exact-match filter and silently overwriting the stored profile. - Change extraction contract to structured JSON {"changed": bool, "profile": str} so the LLM has an unambiguous way to express "nothing to extract" - Wire _call_llm_for_extraction to llm_json_text_with_fallback to enforce response_format=json_object at the API level for capable models - Add three-layer parse fallback: JSON parse → exact-match list → plain-text passthrough for models that don't support structured output - Drop _NOOP_PROFILE_RE: regex broad enough to catch all no-op phrasing also matches valid profile content, making false positives unavoidable - Add 14 unit tests covering all layers, edge cases, and the core regression Fixes oceanbase#933
…plit .env.example (closes oceanbase#940 oceanbase#941 oceanbase#949 oceanbase#948 #) (oceanbase#945) * feat(embedder): zero-config startup with built-in local default embedder Closes oceanbase#940, closes oceanbase#941. Previously a fresh MemoryConfig() defaulted to OpenAIEmbeddingConfig and text-embedding-3-small, which made the "default" path require an OPENAI_API_KEY before the system could run — no real zero-config story. This change introduces a built-in default embedder that mirrors pyseekdb's DefaultEmbeddingFunction (sentence-transformers/all-MiniLM-L6-v2 via ONNX, 384 dims) so PowerMem boots end-to-end with no API key and no external service. The model auto-downloads to the local cache on first use and runs entirely locally afterwards. Switching to a production embedder is a single config field. Alongside that, .env.example is split into a minimal version (just the LLM key block, ~5 vars) and .env.example.full (every existing knob, grouped by component) so first-time users aren't drowned in options. README, README_CN, and README_JP all point at both files. Changes: - New PyseekdbDefaultEmbedding wrapper + PyseekdbDefaultEmbeddingConfig registered under provider name "default" - MemoryConfig.embedder.default_factory now PyseekdbDefaultEmbeddingConfig - .env.example trimmed to the strictly required keys; full reference moved to .env.example.full with an updated header that points back - README / README_CN / README_JP updated to reflect zero-config defaults - Unit tests: embedder round-trip, factory registry, and zero-config MemoryConfig() (mock pyseekdb so no model download in CI) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(storage): seekdb as the default vector store, sharing OceanBase backend Adds `seekdb` as a first-class database provider name, registered to the same `OceanBaseVectorStore` class as `oceanbase` (SeekDB is OceanBase running embedded — same engine, same SQL surface, only configuration differs). Promotes seekdb to the default everywhere it matters: - MemoryConfig.vector_store.default_factory: SQLiteConfig -> SeekDBConfig - DatabaseSettings.provider env default: "sqlite" -> "seekdb" - core/memory.py storage_type fallback: "oceanbase" -> "seekdb" - deprecated create_config() / CreateConfigOptions default also updated `SeekDBConfig` subclasses `OceanBaseConfig` and only overrides what differs: provider name, embedded-mode defaults (empty host, on-disk `./seekdb_data`), and `SEEKDB_*` env var aliases (each falls back to the corresponding `OCEANBASE_*` alias, so users can flip `DATABASE_PROVIDER` between `seekdb` and `oceanbase` without rewriting their `.env`). Same treatment for `SeekDBGraphConfig` on the graph-store side. .env.example.full reorders the database section to lead with embedded SeekDB, and `.env.example` (minimal) now advertises SeekDB + the local embedder as the zero-config defaults. README/CN/JP follow suit. Tests: 7 new unit tests pin the contract — provider registration, shared class path between `seekdb` and `oceanbase`, embedded-mode defaults, SEEKDB_* env aliases, MemoryConfig() default, and DatabaseSettings() default. Full unit suite: 193 passed (up from 186). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(brand): lowercase 'SeekDB' -> 'seekdb' in all user-visible text Per product branding, the canonical spelling is lowercase `seekdb`. This commit normalizes every user-visible occurrence across the repo: - Config templates: .env.example, .env.example.full - READMEs: README.md, README_CN.md, README_JP.md - Docs: docs/api/0002-async_memory.md - Python docstrings, Field descriptions, comments, log/error strings in storage/, utils/, cli/, user_memory/, core/memory.py, server/, script/ Intentionally kept (these are code identifiers, not documentation): - Class names: `SeekDBConfig`, `SeekDBGraphConfig` (renaming would break the public API and violate PascalCase convention for Python classes) - Env var prefixes: `SEEKDB_*` (matches the existing `OCEANBASE_*` convention — ALL_CAPS for env variables is independent of the brand spelling) Tests still green: 193 passed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * deps: bump pyseekdb floor to >=1.3.0 (latest) Per product direction, when PowerMem uses seekdb it should default to the latest seekdb. The previous floor `>=0.1.0` was permissive enough to resolve to long-superseded releases on fresh installs; bump it to `>=1.3.0` so users get the current engine (matching what is already installed in CI / dev environments). Tests still green: 193 passed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(env): reframe .env.example escape hatch as cherry-pick from .full The previous wording told users to `cp .env.example.full .env` when they wanted to tune anything, which throws away the curated minimal file and exposes the wall of knobs we deliberately hid. The new framing matches how the file is actually meant to be used: keep .env minimal, and additively pull individual blocks from .env.example.full when the environment offers stronger infrastructure (OceanBase cluster, hosted embedding LLM, rerank LLM, etc.) or you need more performance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(env): rewrite .env.example* comments — purpose, recommendation, alternatives Restructures every section's annotations in both files so each variable now documents three things explicitly: 1. What the config *does* — the actual effect, not just the field name. 2. A recommended value with a short reason. 3. Alternative options so the reader knows the recommendation is a default, not a constraint. In .env.example (minimal), the single LLM block now explains each variable (provider / key / model) with named alternatives per provider (qwen-plus → qwen-max / qwen-turbo / gpt-4o / claude-sonnet-4-6 / local Ollama models). In .env.example.full, every numbered section gets the same treatment: database providers (with the seekdb ↔ oceanbase symmetry), LLM, embedding, rerank, agent scoping, Ebbinghaus decay, performance batches/caches, security + encryption, telemetry, audit, logging, skill store, graph store, sparse embedding, query rewrite, HTTP server (bind / auth / rate limit / CORS), custom prompts. Each section header also briefly states what subsystem the block configures and when to bother touching it. No code changes. 193/193 unit tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(storage): symmetric SEEKDB_* aliases for schema-shape fields Before this change, a user running DATABASE_PROVIDER=seekdb could configure the connection (SEEKDB_PATH, SEEKDB_DATABASE, …) and vector index (SEEKDB_ INDEX_TYPE, SEEKDB_VECTOR_METRIC_TYPE, SEEKDB_EMBEDDING_MODEL_DIMS) with SEEKDB_* keys, but had to drop down to OCEANBASE_TEXT_FIELD / VECTOR_FIELD / PRIMARY_FIELD / METADATA_FIELD / VIDX_NAME for the table column names. That asymmetry forced mixed-namespace .env files for anyone integrating with an existing schema under seekdb — exactly the friction the SEEKDB_* aliases were introduced to remove. This commit adds SEEKDB_TEXT_FIELD, SEEKDB_VECTOR_FIELD, SEEKDB_PRIMARY_ FIELD, SEEKDB_METADATA_FIELD, and SEEKDB_VIDX_NAME aliases on SeekDBConfig, each with the matching OCEANBASE_* alias kept as a fallback for migrations. .env.example.full documents them in the seekdb section, and the OceanBase section cross-references back to it. Tests pin both directions: SEEKDB_* primary wins, OCEANBASE_* fallback still resolves. Suite: 195 passed (up from 193). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(storage): close last SEEKDB_* parity gaps — pool, sparse, native hybrid Audit found four OCEANBASE_* env aliases with no SEEKDB_* counterpart: - OCEANBASE_POOL_RECYCLE (pool_recycle) - OCEANBASE_POOL_PRE_PING (pool_pre_ping) - OCEANBASE_INCLUDE_SPARSE (include_sparse) - OCEANBASE_ENABLE_NATIVE_HYBRID (enable_native_hybrid) This forced a mixed-namespace .env for anyone tuning the connection pool, enabling sparse vectors, or pushing hybrid ranking into the engine's native SQL extension under DATABASE_PROVIDER=seekdb — exactly the inconsistency the SEEKDB_* aliases were introduced to remove. This commit adds the four missing aliases on SeekDBConfig, with the matching OCEANBASE_* keys kept as fallbacks for migrations. Documented honestly in .env.example.full: - Pool knobs are no-ops in embedded mode (NullPool), useful when seekdb points at a remote host. - SEEKDB_INCLUDE_SPARSE is a shortcut for the SPARSE_VECTOR_ENABLE switch in section 14 (both aliases still resolve). - SEEKDB_ENABLE_NATIVE_HYBRID requires seekdb ≥1.3 or OceanBase ≥4.5. The OceanBase section cross-references the same tunables instead of duplicating the docs. After this commit, `diff` of OCEANBASE_* vs SEEKDB_* aliases on the config class is empty — perfect parity. Tests: two new — SEEKDB_* primary aliases bind, OCEANBASE_* fallback still resolves. Suite: 197 passed (up from 195). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(storage): hard namespace isolation between seekdb and oceanbase configs Three related changes that lock in the contract "seekdb reads SEEKDB_*, oceanbase reads OCEANBASE_* — no cross-reading": 1. SeekDBConfig drops every OCEANBASE_* fallback alias. Previously a seekdb-configured deployment could silently inherit settings from OCEANBASE_* keys lying around in the env; now those keys are ignored entirely. The only cross-cutting alias kept is SPARSE_VECTOR_ENABLE, which is a generic feature toggle (not OceanBase-namespaced) shared by all providers. 2. OceanBaseConfig drops the ob_path field. OCEANBASE_PATH is a seekdb concept (the embedded on-disk data directory). Setting it while DATABASE_PROVIDER=oceanbase now raises a clear validation error pointing the user at DATABASE_PROVIDER=seekdb / SEEKDB_PATH instead. OceanBaseConfig.host's default flips from "" to "127.0.0.1" and a field validator rejects empty values, so there is no silent fall- through to embedded mode under the oceanbase provider. The validator is scoped to the OceanBaseConfig class itself so SeekDBConfig (which keeps host="" as the embedded-mode signal) is unaffected. 3. SEEKDB_ENABLE_NATIVE_HYBRID default flips from false to true. This branch already pins pyseekdb>=1.3.0, which ships the native hybrid SQL extension, so the new default matches what the engine actually supports out of the box. .env.example.full documents the new contract: the seekdb section calls out "namespace isolation" explicitly, the OceanBase section notes that OCEANBASE_PATH is rejected and that OCEANBASE_HOST is required. Tests cover: SeekDBConfig ignores OCEANBASE_* env keys, OceanBaseConfig rejects empty host, OceanBaseConfig rejects OCEANBASE_PATH env, the OCEANBASE_PATH rejection does NOT fire on the SeekDBConfig subclass, and SEEKDB_ENABLE_NATIVE_HYBRID defaults to True. Suite: 201 passed (up from 197). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(storage): move pool tuning to oceanbase only; activate OCEANBASE_* docs Audit of the storage backend (oceanbase.py:200-220) confirms which of the four shared knobs are actually live on each code path: - POOL_RECYCLE / POOL_PRE_PING — read only inside `if host:` (the remote-cluster branch). Embedded seekdb uses NullPool and never reads them. - INCLUDE_SPARSE / ENABLE_NATIVE_HYBRID — read in both branches; both backends genuinely use them. So the two pool knobs are oceanbase-only. This commit removes them from the seekdb namespace end-to-end and adds active code-level rejection so a misconfiguration surfaces loudly instead of silently doing nothing: - SeekDBConfig now overrides pool_recycle / pool_pre_ping with no env aliases (so OCEANBASE_POOL_* cannot bleed through), and a model_validator on SeekDBConfig raises ValueError if either SEEKDB_POOL_RECYCLE or SEEKDB_POOL_PRE_PING is set in the environment — the error message points the user at the OCEANBASE_POOL_* equivalents. - .env.example.full drops the SEEKDB_POOL_* entries from the seekdb block entirely. - The OceanBase block flips its previously commented-out hint lines into active, fully-documented settings (purpose / recommended / other-options format) for OCEANBASE_POOL_RECYCLE, OCEANBASE_POOL_PRE_PING, OCEANBASE_INCLUDE_SPARSE, OCEANBASE_ENABLE_NATIVE_HYBRID. INCLUDE_SPARSE and ENABLE_NATIVE_HYBRID stay on both providers — same field, namespace-isolated aliases (SEEKDB_* vs OCEANBASE_*), with provider-appropriate defaults (seekdb ships ≥1.3 with native hybrid on; OceanBase defaults to off to remain safe for older clusters). Tests: two new ones pin that SEEKDB_POOL_RECYCLE / SEEKDB_POOL_PRE_PING env vars are rejected with a clear error. Suite: 203 passed (up from 201). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * revert(storage): drop seekdb-as-separate-provider; use oceanbase for both modes Since the seekdb backend supports a remote-server mode in addition to its embedded on-disk mode, splitting it into its own first-class provider was overshoot — the OceanBase config surface already expresses both shapes (empty OCEANBASE_HOST = embedded seekdb; non-empty = remote cluster). This commit removes the SeekDBConfig / SeekDBGraphConfig classes, the `seekdb` provider registration, the SEEKDB_* env namespace, the OCEANBASE_* fallback isolation, the OCEANBASE_PATH rejection, the required-host validator on OceanBaseConfig, and the dedicated .env block. The zero-config startup story still holds — just delivered through a single provider: - DATABASE_PROVIDER default switches from "seekdb" to "oceanbase". - MemoryConfig.vector_store default_factory becomes OceanBaseConfig (which already defaulted to host="" → embedded seekdb at ./seekdb_data). - core/memory.py storage_type fallback returns to "oceanbase". - .env.example minimal block describes the single-provider default ("OceanBase with no host = embedded seekdb"). - .env.example.full collapses the previous separate seekdb + oceanbase blocks into one OceanBase section that documents both modes inline, with each variable still annotated with purpose / recommended / alternatives. - READMEs (en / cn / jp) match. What is **kept** from the rest of PR oceanbase#945, since it stands independent of the storage decision: the built-in default embedder (issue oceanbase#941), the pyseekdb>=1.3.0 dep floor, the .env.example minimal/full split (issue oceanbase#940), and the per-section purpose/recommended/alternatives doc style. Tests rewritten to match: 189 passed in the full unit suite. Clean-env smoke check confirms `MemoryConfig()` with no env vars produces an OceanBaseConfig with host="" and ob_path="./seekdb_data" (embedded seekdb mode), with the built-in local embedder. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(env): point readers at .env.example.full for *_LLM_BASE_URL overrides Some deployments (corporate proxies, private gateways, self-hosted ollama/vllm endpoints) need to override the default base URL for the chosen LLM provider. Those settings deliberately live in .env.example.full, not in the minimal file. Add a short note in .env.example's LLM block telling readers exactly where to look and which variable names to cherry-pick (QWEN_LLM_BASE_URL, OPENAI_LLM_BASE_URL, etc.). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(env): switch EMBEDDING_PROVIDER block in .env.example.full to default The full reference advertised qwen as the embedding provider, but the zero-config default the code actually ships is the built-in local `default` provider (PyseekdbDefaultEmbedding, all-MiniLM-L6-v2, 384d). Having the docs disagree with the wired default was confusing — copying the full file would silently switch users from local to cloud embeddings and require an API key. This commit aligns the block with the code: - EMBEDDING_PROVIDER=default - EMBEDDING_MODEL=all-MiniLM-L6-v2 - EMBEDDING_DIMS=384 (and matches the OCEANBASE_EMBEDDING_MODEL_DIMS default in section 1) - EMBEDDING_API_KEY commented out (the default needs none; uncomment when switching providers) - Recommended / Other options re-ordered: `default` is now first with the rationale, cloud / self-hosted providers listed as upgrades. Smoke-checked: `EMBEDDING_PROVIDER=default` + `EMBEDDING_MODEL= all-MiniLM-L6-v2` + `EMBEDDING_DIMS=384` resolves end-to-end through EmbeddingSettings.to_config(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: zero-config defaults — local embedder, port 8848, one-click skill & docs - embedder: default EMBEDDING_PROVIDER to the built-in local all-MiniLM-L6-v2 embedder (384 dims, no API key) so PowerMem starts with true zero config; set EMBEDDING_PROVIDER to switch to a cloud provider (oceanbase#941) - server: change default listening port 8000 -> 8848 across core config, CLI help, Makefile, Docker (Dockerfile/compose/entrypoint), claude-code-plugin hook, examples, VS Code extension and regression tests (oceanbase#949) - claude-code-plugin: add one-click SETUP.md / UNINSTALL.md, marketplace.json and refreshed hooks for install-and-go agent wiring (oceanbase#942) - docs: add per-agent setup guide (docs/integrations/claude_code.md, overview) and refresh README / README_CN / README_JP / getting-started (oceanbase#943) - chore: ignore seekdb_data/; black-reformat config_loader.py and utils.py Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add more detais for setup * add error handling * add error handling * Added cache-first model loading with a 30s download timeout and pyseekdb cache injection to pyseekdb_default.py * Removed /tmp/powermem-server.log redirections (server auto-logs to server.log), documented log file locations (server.log + * fix(ci): make pyseekdb a core dep, mock embedder preload in tests, fix doc links Resolves the three CI failures on the PR: - test (3.11/3.12): the zero-config default embedder requires pyseekdb, but it lived in the optional `seekdb` extra, so the unit tests errored with `ModuleNotFoundError: No module named 'pyseekdb'`. Move pyseekdb into core `dependencies` (it backs the default embedder) and keep an empty `seekdb` extra for `powermem[seekdb]` backward compatibility. The fixture now also stubs `_load_sentence_transformer_with_fallback` so the test no longer imports `sentence_transformers` (an optional extra) nor hits the network on a cache miss. - test-frontend: the new docs/integrations/claude_code.md linked to repo paths under `apps/...` via `../../apps/...`, which Docusaurus could not resolve and failed the build (onBrokenLinks: throw). Rewrite all 12 such links to absolute GitHub URLs (directories use /tree/, files use /blob/). Verified locally with a full `npm run build` — no broken links. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(embedder): make sentence_transformers pre-warm optional for true zero-config The zero-config default embedder hard-imported `sentence_transformers` inside `_load_sentence_transformer_with_fallback`, but that package only ships in the optional `extras` group. After promoting `pyseekdb` to a core dependency, a clean `pip install powermem` would get pyseekdb yet still crash when building the default embedder. Wrap the import in try/except: when sentence_transformers is absent we skip the cache-first pre-warm and let pyseekdb's DefaultEmbeddingFunction load the model itself via onnxruntime. The embedder works out of the box; installing the `extras` group still enables the huggingface.co-hang avoidance optimization. Also drop the unused `import os`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add other llm base url to ease use * fix(test): patch embedder preload via patch.object, not a dotted string CI (Python 3.11.15 / 3.12.13) failed with: AttributeError: module 'powermem.integrations.embeddings' has no attribute 'pyseekdb_default' On these interpreter builds, unittest.mock resolves a dotted patch target via pkgutil.resolve_name, which does NOT auto-import the final submodule. Since nothing had imported `pyseekdb_default` yet at fixture-setup time, the attribute lookup on the package failed. (Older 3.12.x builds auto-import via mock's own _importer, which is why it passed locally.) Import the submodule explicitly at module top and patch the live module object with patch.object(...), which does no string resolution. Fixes both the test (3.11) and test (3.12) jobs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(deps): declare loguru as a core dependency `pyseekdb_default.py` uses loguru for logging (the project's logging style), but loguru was never declared in pyproject. It happened to be importable in some environments, so this stayed hidden until the unit test imported the module at collection time, failing CI with: ModuleNotFoundError: No module named 'loguru' Add `loguru>=0.7.0` to core dependencies so the import resolves everywhere and the codebase keeps a single, unified logging library. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(embedder): use stdlib logging in pyseekdb_default, drop loguru dep pyseekdb_default.py was the only module in the codebase importing loguru; the other 72 source files use the stdlib `logging` module with a central `logging_config.py` (and `log_context.py` for request_id/user_id/agent_id context). Adding loguru as a dependency just to support one outlier file was the wrong direction — it also bypassed the project's central logging configuration. Switch the file to `logger = logging.getLogger(__name__)` and convert the loguru `{}`-style messages to stdlib `%s` lazy formatting, matching the rest of the project. Revert the previously-added `loguru` core dependency. This also fixes the CI collection error (`ModuleNotFoundError: No module named 'loguru'`) without introducing a new dependency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: zhongyan.feng <zhongyan.feng@oceanbase.com>
oceanbase#954) * docs(integrations): add per-client setup guides and unify MCP defaults (fixes oceanbase#943) Add integration docs, agent-driven SETUP/UNINSTALL guides, shared MCP config writers, mount /mcp on powermem-server, and align default MCP port to 8848. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): unblock VS Code packaging and Docusaurus build Add extension repository metadata and vsce flags for SETUP.md links, replace out-of-tree integration doc links with GitHub URLs, and ignore generated docs/website artifacts. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…se#938) Unify _generate_review_schedule and get_review_schedule via shared review_adjustment_factor (default 0.3) and review_interval_min_hours. Add prefer_stored to get_review_schedule for DB-aligned queries. Add unit tests.
…base#953) Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 3.2.4 to 4.1.0. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…eanbase#956) Runtime forget checks and search re-ranking now resolve per-memory decay strength via _resolve_decay_rate(). Default decay_rate_multipliers are adjusted so working < short_term < long_term under exp(-t/(24*S)). Add regression tests and pytest pythonpath for reliable imports. Fixes oceanbase#955
…nbase#965) * feat: support OpenAI provider default headers * ci: install seekdb extras for regression tests * ci: harden regression environment setup
…/top_p conflict (oceanbase#961) SETUP.md improvements: - Step 2: add auto-detect flow reading LLM config from ~/.claude/settings.json - Step 2: document Anthropic model name normalization (dots → dashes, e.g. claude-sonnet-4.6 → claude-sonnet-4-6); settings.json uses dots, API requires dashes - Step 3a: move embedding model download to background immediately after pip install, so it runs in parallel with hook build and plugin staging - Step 3a: fix plugin uninstall idempotency — add `2>/dev/null || true` to swallow "not found" error when plugin was never installed - Error guide: add [E010] Anthropic temperature+top_p conflict — diagnosis and fix Bug fix: - AnthropicLLM.generate_response: pop top_p before sending to Anthropic API. Anthropic rejects requests where both temperature and top_p are specified (400). Verified with direct API call: temperature-only and top_p-only both succeed; sending both always returns 400 invalid_params. Co-authored-by: Claude Sonnet 4 <noreply@anthropic.com>
* docs: Add comprehensive Web Dashboard user guide (issue oceanbase#959) - Create docs/guides/0013-dashboard.md with complete dashboard walkthrough - Getting started: server startup, Docker deployment, access patterns - Authentication: API key configuration and dashboard setup - Page-by-page documentation: Overview, Memories, User Profile, Settings - Common workflows: inspect memories, debug retrieval, monitor health - Troubleshooting: 404, 401, stale data, rebuild steps - Relationship to other interfaces (SDK, CLI, VS Code extension) - Update README.md and README_CN.md with dashboard guide links - Add description in HTTP API server + Dashboard section - Add to Docs section for easy discovery - Update docs/guides/overview.md index - Add to Getting Started section - Add to Quick Navigation section - Update docs/api/0005-api_server.md - Add reference to dashboard user guide after build instructions Addresses issue oceanbase#959: Document the Web Dashboard and guide users through the frontend UI * docs: Add notes to skip server startup if already running - Update docs/api/0005-api_server.md with note before server startup section - Update docs/guides/0013-dashboard.md in multiple locations: - Getting Started section: note to skip if server is running - Authentication section: clarify restart vs start - Troubleshooting 404 section: note to skip restart if not running - Rebuilding assets section: note to skip restart if not running - 401 troubleshooting: clarify restart vs start Helps users avoid confusion when server is already running from a previous session. * docs: Add Web Dashboard guide link to README_JP.md - Update HTTP API Server section with dashboard access URL and guide link - Add Web Dashboard to Docs section for Japanese README - Consistent with README.md and README_CN.md updates Addresses issue oceanbase#959 * fix: resolve broken links in dashboard guide causing CI build failure - Change docker/README.md links to absolute GitHub URLs (outside docs/) - Fix development/overview.md relative path from ../../docs/ to ../ - These paths were incorrectly normalized by remark-normalize-doc-links causing Docusaurus onBrokenLinks: 'throw' to fail the build
… provenance
Track the origin of memory and skill records via dedicated link tables.
A source represents the raw input (conversation turn, file upload, API
call) that produced one or more downstream records. memory.add() now
auto-creates a source and links every extracted fact back to it.
Schema:
- {collection}_sources -- source records
- {collection}_sources_memory_links -- many-to-many: source <-> memory
- {collection}_sources_skill_links -- many-to-many: source <-> skill
Migration: existing {collection}_sources_links tables are auto-renamed
to {collection}_sources_memory_links on init (metadata-only RENAME,
fast and atomic).
API additions on Memory:
- create_source / get_source / delete_source
- link_memory_to_source / unlink_memory_from_source / get_sources_for_memory
- link_skill_to_source / unlink_skill_from_source / get_sources_for_skill
- get_memories_for_source / get_skills_for_source
Source linking in add() is best-effort: failures are logged but never
fail the add call itself.
…se#968) * fix(llm): wire base_url into AnthropicLLM and ZaiLLM clients AnthropicConfig already declares `anthropic_base_url` (env: ANTHROPIC_BASE_URL) and ZaiConfig already declares `zai_base_url` (env: ZAI_BASE_URL), but neither value was forwarded to the SDK client constructor. For Anthropic: pass base_url to anthropic.Anthropic(). For ZAI: Zhipu AI exposes an OpenAI-compatible endpoint, so replace the ZhipuAiClient dependency with openai.OpenAI and pass base_url directly — no behavioural change since the response format is identical. * test(llm): add unit tests for Anthropic and ZAI base_url configuration
…ceanbase#970) * fix(ci): keep mcp optional for api server * fix: avoid exiting on optional dependency imports * test: skip server optional mcp test without fastapi
…sh translations, Python interpreter detection (oceanbase#969) - Add AskUserQuestion after server health check: ask user whether to build and open the Web Dashboard via make server-dashboard-start - Translate E010 error entry from Chinese to English - Detect correct Python interpreter (POWERMEM_PYTHON) from powermem-server shebang immediately after pip install, ensuring modelscope download and the server all use the same environment - Add E011–E014 error entries covering Python version, pip version, internal mirror missing packages, and transitive dependency gaps - Update PRE-CHECK section to cover Python 3.11, pip >= 21.3, and mirror access checks - Improve Method A setup steps: upgrade pip before editable install
* test: add claude marketplace entry * test: add claude powermem init skills * test: document unpublished powermem init package * test: harden claude init flow * test: reuse setup model preload flow * docs: clarify claude marketplace backend install
…ersistence (oceanbase#986) Extend automated SETUP/UNINSTALL for CodeFuse alongside Cursor/VS Code/Qoder, replace fetch with Node.js http/https for extension-host compatibility, add health-check retries with logging, and add LaunchAgent scripts so powermem-server survives IDE restarts on macOS. Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(ci): add license header check and missing headers * chore(ci): fix license checks and refresh E2E checksums * fix(ci): preserve license header in JS generator --------- Co-authored-by: Chojan Shang <psiace@apache.org>
* chore(release): prepare v0.0.2 * docs: refine README tagline
* feat: add human-agent work continuity * docs: assign RFC 1223 * docs: link work continuity issue * feat: complete handoff continuity loop * docs(rfc): clarify work continuity with examples * feat(server): refine handoff dashboard experience * fix(claude-code): align setup and handoff scope * feat(mcp): add handoff workstream picker * fix(server): refine handoff report web experience * feat(server): improve handoff report navigation * feat(server): unify handoff report editing * fix(codex): align evaluation trace scope mocks * fix(dsh): preserve license headers in build * chore(license): add missing headers
* implement hermes plugin * fix comments * fix memory extractrion error * memory_ref.revision * update readme * fix yaml and sync * ruff format * fix comments * update readme * add header * add header
* feat(website): refresh documentation theme * fix(website): align visual details with target * fix(website): simplify code block framing * refactor(website): configure landing content * docs(website): refine homepage and docs copy * docs(website): refine homepage copy and layout * fix(website): prevent changelog title wrapping * fix(website): stack changelog introduction * refactor(website): unify editorial page layout * fix(website): unify footer layout * refactor(website): remove obsolete layout styles * fix(website): align record pagination * fix(website): keep documentation sidebars visible * fix(website): restore sticky documentation sidebars * fix(website): keep sidebar containers viewport-sized * fix(website): center record navigation layout * refactor(website): remove obsolete site files
…ror`. (oceanbase#1274) * fix cursor concunrrcy bug * fix comment on test
…ct-en fix(website): redirect root to English site
* build: derive package version from vcs * fix: stabilize dynamic version checks * fix(e2e): provide fallback version in harness build * fix(e2e): propagate version to agent install * fix(e2e): enforce VCS version in container builds
…ercontext cli (oceanbase#1287) * feat(hermes): add Hermes memory provider setup and diagnostics * update readme * fix comment
* feat(pi): add native Pi package * fix(pi): harden package compatibility * fix(pi): remove unverified version gate * feat(pi): align tools with Claude Code * fix(pi): complete Claude Code parity * refactor(pi): narrow native tool surface * fix(integrations): secure explicit writes and Git sources * docs: align integration installation refs * fix(integrations): harden remote setup * fix(pi): harden secret capture checks * fix(pi): retain captures after flush failures
|
twotwotwo seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Member
|
ruff format failed |
…ceanbase#1282) * feat(integrations): add OpenClaw memory plugin * chore(integrations): add OpenClaw license headers * style(integrations): format OpenClaw plugin metadata * docs(openclaw): use managed plugin installation flow * chore(integrations): defer OpenClaw documentation * feat(integrations): add OpenClaw setup flow * fix(integrations): initialize OpenClaw gateway mode * chore(integrations): satisfy CI formatting and licensing
…base#1299) * docs(rfc): propose local Server service installation * docs(rfc): assign RFC 1299 * docs(rfc): address initial review feedback * docs(rfc): tighten service lifecycle contracts
Author
|
Fixed in the latest commit; ruff format now passes locally. |
222twotwotwo
force-pushed
the
fix/windows-hook-unicode-prompts
branch
2 times, most recently
from
August 23, 2026 09:04
d499150 to
7190a27
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Which issue or RFC does this PR close?
Closes #1305
Rationale for this change
On Windows, the Claude Code and Codex hook scripts could read stdin using the local console encoding instead of UTF-8. That corrupted non-ASCII prompts and could produce lone surrogate characters. The server then failed while rendering the 422 validation response because the raw invalid input was included in the returned error details.
What changes are included in this PR?
The Claude Code and Codex hook scripts now read JSON payloads from
sys.stdin.bufferand decode them as UTF-8 before parsing.The server’s
RequestValidationErrorhandler now removes the rawinputfield from validation errors before returning the 422 response.Regression tests were added for UTF-8 stdin handling on Windows and for surrogate-safe validation responses.
Are there any user-facing changes?
Yes. Windows users submitting non-ASCII prompts through Claude Code or Codex hooks should no longer see corrupted prompts or broken validation responses.
The API still returns 422 for invalid requests, but it no longer echoes the raw invalid input in the error details.
How was this change tested?
pytest tests/test_server.py -q -k "invalid_request_without_input_field or unicode_surrogates_without_crashing"pytest tests/claude_code_plugin/test_hook.py tests/codex_plugin/test_recall.py -qAI usage statement
AI tools were used to implement and verify this change.